﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using FairyGUI;
using System.Text;

namespace Com.ZX.Manager
{
	/// <summary>
	/// 资源信息
	/// </summary>
	public class AssetInfo
	{
		public Type AssetType { get; set; }
		public string Path { get; set; }
		public bool IsLoaded { get { return _AssetObject != null; } }
		public int RefCount { get; set; }

		private UnityEngine.Object _AssetObject;
		public UnityEngine.Object AssetObject
		{
			get
			{
				if (_AssetObject == null)
					_ResourcesLoad();
				return _AssetObject;
			}
		}

		/// <summary>
		/// 同步加载资源 使用协程
		/// </summary>
		/// <param name="_loaded"></param>
		/// <returns></returns>
		public IEnumerator GetAssetCoroutine(Func<UnityEngine.Object,UnityEngine.Object> _loaded)
		{
			while (true)
			{
				yield return null;
                if (_AssetObject == null)
                {
                    _ResourcesLoad();
                    yield return null;
                }
				if (_loaded != null)
					_loaded(_AssetObject);
			}
		}

		/// <summary>
		/// 同步加载资源
		/// </summary>
		private void _ResourcesLoad()
		{
			try
			{
				_AssetObject = Resources.Load(Path);
				if (_AssetObject == null)
					CustomDebug.LogError(" AssetObject is null");
			}
			catch (Exception exc)
			{
				CustomDebug.LogError(exc.Message);
				//throw;
			}
		}

		/// <summary>
		/// 异步加载资源
		/// </summary>
		/// <param name="_loaded"></param>
		/// <returns></returns>
		public IEnumerator GetAssetAsync(Func<UnityEngine.Object, UnityEngine.Object> _loaded)
		{
			return GetAssetAsync(_loaded, null);
		}

		/// <summary>
		/// 异步加载资源
		/// </summary>
		/// <param name="_loaded">资源对象回调</param>
		/// <param name="_progress">加载进度回调</param>
		/// <returns></returns>
		public IEnumerator GetAssetAsync(Func<UnityEngine.Object, UnityEngine.Object> _loaded, Action<float> _progress)
		{
			if (_AssetObject != null)
			{
				_loaded(_AssetObject);
				yield break;
			}
			ResourceRequest resRequest = Resources.LoadAsync(Path);
			while (resRequest.progress < 0.9f)
			{
				if (_progress != null)
					_progress(resRequest.progress);
				yield return null;
			}
			while (!resRequest.isDone)
			{
				if (_progress != null)
					_progress(resRequest.progress);
				yield return null;
			}
			_AssetObject = resRequest.asset;
			if (_loaded != null)
			{
				_loaded(_AssetObject);
			}
		}
	}

	/// <summary>
	/// 资源管理类
	/// </summary>
	public class ResrManager : BaseSingleton<ResrManager>
	{
		private Dictionary<string, AssetInfo> dictAssetInfo = null;

		public ResrManager()
		{
		}

		public override void onInit()
		{
			dictAssetInfo = new Dictionary<string, AssetInfo>();
            //UIPackage.AddPackage()
            StringBuilder strBuild = new StringBuilder(UIDefine.FUI_PACKAGE_ROOT);
            for (int i = 0; i < (int)EnumUIType.MAX_COUNT; i++)
            {
                UIPackage.AddPackage(strBuild.Append(((EnumUIType)i).ToString()).ToString());
                CustomDebug.Log(strBuild.ToString());
            }
			//base.onInit();
		}

		public override void onDestroy()
		{
			//base.onDestroy();
            
		}

		
		/// <summary>
		/// 获取资源信息
		/// </summary>
		/// <param name="path">路径</param>
		/// <returns></returns>
		private AssetInfo GetAssetInfo(string path)
		{
			return GetAssetInfo(path, null);
		}
        AssetInfo temp_assetInfo = null;
        /// <summary>
        /// 获取资源信息
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="assetLoadedCB">回调</param>
        /// <returns></returns>
        private AssetInfo GetAssetInfo(string path,Func<UnityEngine.Object,UnityEngine.Object> assetLoadedCB)
		{
			if (string.IsNullOrEmpty(path))
			{
				CustomDebug.LogError("path is null");
				if (assetLoadedCB != null)
					assetLoadedCB(null);
			}
			
			if (!dictAssetInfo.TryGetValue(path, out temp_assetInfo))
			{
				temp_assetInfo = new AssetInfo();
				temp_assetInfo.Path = path;
				dictAssetInfo.Add(path, temp_assetInfo);
			}
			temp_assetInfo.RefCount++;
            //CustomDebug.Log("引用数"+temp_assetInfo.RefCount);
			return temp_assetInfo;
		}

		#region 实例化资源
		/// <summary>
		/// 同步加载资源并实例化
		/// </summary>
		/// <param name="path">路径</param>
		/// <returns>实例化资源对象</returns>
		public GameObject LoadInstance(string path,System.Action<UnityEngine.GameObject> actionCb=null)
		{
			UnityEngine.Object assetObj = Load(path);
            UnityEngine.GameObject newObj; 
			this.Instantiate(assetObj, out newObj, actionCb);
            //CustomDebug.Log(obj.name);
            return newObj;
		}

        public T LoadInstance<T>(UIInfoData uiInfo) where T:class
        {
            T obj;
            if (typeof(T) == typeof(Window))
            {
                //UIPackage.AddPackage(uiInfo.Path);
                obj= (T)Activator.CreateInstance(Type.GetType(uiInfo.UIType.ToString()));
               
            }
            else if (typeof(T) == typeof(UnityEngine.Object))
            {
                UnityEngine.Object assetObj = Load(uiInfo.Path);
                return Instantiate(assetObj) as T;
            }
            else
            {
                throw new Exception("no suppot type to LoadInstance in the ResrManager.LoadInstance() ");
            }
            return obj;
        }


        //public GComponent 
        /// <summary>
        /// 同步加载资源并实例化 使用协程
        /// </summary>
        /// <param name="path"><路径/param>
        /// <param name="instaceLoadedCB"></param>
        public void LoadInstanceCoroutine(string path, Action<UnityEngine.GameObject> instaceLoadedCB=null)
		{
			//LoadInstance(path, instaceLoaded, null);
			//LoadCoroutine(path, instaceLoaded);
			LoadCoroutine(path, (assetObj) =>
			{
                UnityEngine.GameObject newGO;
                Instantiate(assetObj, out newGO, instaceLoadedCB);
                return newGO;
			});
		}

		/// <summary>
		/// 异步加载资源并实例化 无进度回调
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="instaceLoaded">对象实例化的回调</param>
		public void LoadInstanceAsync(string path, Action<UnityEngine.GameObject> instaceLoadedCB)
		{
			LoadAsync(path, (assetObj) =>
			{
                UnityEngine.GameObject newGO;
                Instantiate(assetObj, out newGO, instaceLoadedCB);
                return newGO;
            });
		}

		/// <summary>
		/// 异步加载资源并实例化 有进度回调
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="instaceLoadedCB"></param>
		/// <param name="progressCB"></param>
		public void LoadInstanceAsync(string path, Action<UnityEngine.GameObject> instaceLoadedCB, Action<float> progressCB)
		{
			LoadAsync(path, (assetObj) => 
			{
                UnityEngine.GameObject newGO;
                Instantiate(assetObj, out newGO, instaceLoadedCB);
                return newGO;
			}, progressCB);
		}

		/// <summary>
		/// 实例化对象 无回调
		/// </summary>
		/// <param name="assetObj">待实例化的资源对象</param>
		/// <returns>实例化对象</returns>
		private UnityEngine.Object Instantiate(UnityEngine.Object assetObj)
		{
            UnityEngine.Object resultObj = null;
            resultObj = Instantiate(assetObj);
            return resultObj;
        }

		/// <summary>
		/// 实例化方法 有回调
		/// </summary>
		/// <param name="assetObj">待实例化的资源对象</param>
		/// <param name="instaceLoadedCB">实例化的回调</param>
		/// <returns>实例化对象</returns>
		private GameObject Instantiate(UnityEngine.Object assetObj, out UnityEngine.GameObject newGO, Action<UnityEngine.GameObject> instaceLoadedCB)
		{
            newGO =null;
			if (assetObj != null)
			{
				newGO = UnityEngine.GameObject.Instantiate(assetObj) as GameObject;
				if (newGO != null)
				{
					if (instaceLoadedCB != null)
						instaceLoadedCB(newGO);
				}
				//else
				//{
				//	CustomDebug.Log("newGO was null");
				//}
			}
			else
			{
				CustomDebug.Log("assetObj was null");
			}
			return newGO;
		}
		#endregion

		#region 加载资源 Load

		/// <summary>
		/// 同步加载
		/// </summary>
		/// <param name="path">路径</param>
		/// <returns>asset 对象</returns>
		public UnityEngine.Object Load(string path)
		{
			AssetInfo assetInfo = GetAssetInfo(path);
			if (assetInfo != null)
				return assetInfo.AssetObject;
			return null;
		}

		/// <summary>
		/// 同步加载 使用协程
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="assetLoadedCB">对象回调</param>
		public void LoadCoroutine(string path, Func<UnityEngine.Object, UnityEngine.Object> assetLoadedCB=null)
		{
			AssetInfo assetInfo = GetAssetInfo(path,assetLoadedCB);
			if (assetInfo != null)
				MonoControlHelper.inst.StartCoroutine(assetInfo.GetAssetCoroutine(assetLoadedCB));
		}

		/// <summary>
		/// 异步加载 无进度回调
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="assetLoaded">对象回调</param>
		public void LoadAsync(string path, Func<UnityEngine.Object, UnityEngine.Object> assetLoadedCB)
		{
			LoadAsync(path, assetLoadedCB, null);
		}

		/// <summary>
		/// 异步加载 有进度回调
		/// </summary>
		/// <param name="path">路径</param>
		/// <param name="assetLoadedCB">对象回调</param>
		/// <param name="progressCB">进度回调</param>
		public void LoadAsync(string path, Func<UnityEngine.Object, UnityEngine.Object> assetLoadedCB, Action<float> progressCB)
		{
			AssetInfo assetInfo = GetAssetInfo(path, assetLoadedCB);
			if (assetInfo != null)
			{
				MonoControlHelper.inst.StartCoroutine(assetInfo.GetAssetAsync(assetLoadedCB, progressCB));
				//CustomDebug.Log("count:" + assetInfo.RefCount);
			}
		}

        #endregion

        public void ClearNoUsedAssets()
        {
            Resources.UnloadUnusedAssets();
        }
	}
}
